home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 1996 September / Software of the Month Club 1996 September.iso / mac / Software Research Institute-SRI / Business / Alpha ƒ / Tcl / SystemCode / latexSmart.tcl < prev    next >
Encoding:
Text File  |  1995-10-06  |  9.1 KB  |  356 lines  |  [TEXT/ALFA]

  1. #############################################################################
  2. #############################################################################
  3. #
  4. # latexSmart.tcl (called from latex.tcl)
  5. #
  6. # Smart quotes, dots, subscripts, superscripts, and fillParagraph
  7. #
  8. #############################################################################
  9. #
  10. # Original author unknown
  11. #
  12. # Maintainer:  Tom Scavo <trscavo@syr.edu>
  13. #
  14. # Fill routines by:  Vince Darley <vince@das.harvard.edu>
  15. #
  16. #############################################################################
  17. #############################################################################
  18.  
  19. #--------------------------------------------------------------------------
  20. # Smart quotes:
  21. #--------------------------------------------------------------------------
  22.  
  23. proc smartDQuote {} {
  24.     global TeXmodeVars
  25.     if {[isSelection]} { deleteSelection }
  26.     if { !$TeXmodeVars(smartQuotes) || [literalChar] } { insertText {"}; return }
  27.     if {[leftQ]} {
  28.         insertText {``}
  29.     } else {
  30.         insertText {''}
  31.     }
  32. }
  33.  
  34. # bind double quote:
  35. ascii 0x22 <s> smartDQuote TeX
  36.  
  37. proc smartQuote {} {
  38.     global TeXmodeVars
  39.     if {[isSelection]} { deleteSelection }
  40.     if { !$TeXmodeVars(smartQuotes) || [literalChar]  } { insertText {'}; return }
  41.     if {[leftQ]} {
  42.         insertText {`}
  43.     } else {
  44.         insertText {'}
  45.     }
  46. }
  47.  
  48. # bind single quote:
  49. ascii 0x27 smartQuote TeX
  50.  
  51. proc leftQ {} {
  52.     if { [getPos] == 0 } { return 1 };
  53.     set q [lookAt [expr [getPos]-1]]
  54.     case $q in {
  55.         {\t}  {return 1}
  56.         {(}  {return 1}
  57.         {\{}  {return 1}
  58.         {[}  {return 1}
  59.         {<}  {return 1}
  60.         {\ } {return 1}
  61.         {\r} {return 1}
  62.     }
  63.     return 0
  64. }
  65.  
  66. #--------------------------------------------------------------------------
  67. # Smart dots:
  68. #--------------------------------------------------------------------------
  69.  
  70. proc smartDots {} {
  71.     global TeXmodeVars
  72.     if {[isSelection]} { deleteSelection }
  73.     if { !$TeXmodeVars(smartDots) || [literalChar] } { insertText {.}; return }
  74.     if {[lookAt [expr [set endPos [getPos]]-1]] == "."} then {
  75.         if {[lookAt [set begPos [expr $endPos-2]]] == "."} then {
  76.             replaceText $begPos $endPos "\\ldots"
  77.         } else {
  78.             insertText "."
  79.         }
  80.     } else {
  81.         insertText "."
  82.     }
  83. }
  84.  
  85. # bind period:
  86. ascii 0x2e smartDots "TeX"
  87.  
  88. #--------------------------------------------------------------------------
  89. # Smart subscripts and superscripts:
  90. #--------------------------------------------------------------------------
  91.  
  92. proc smartSubscripts {} {
  93.     smartScripts {_}
  94. }
  95.  
  96. proc smartSuperscripts {} {
  97.     smartScripts {^}
  98. }
  99.  
  100. proc smartScripts {char} {
  101.     global TeXmodeVars
  102.     if {[isSelection]} { deleteSelection }
  103.     if { !$TeXmodeVars(smartScripts) || [literalChar] } then {
  104.         insertText $char
  105.         return
  106.     }
  107.     if { $TeXmodeVars(smartScripts) } then {
  108.         if { $char == {_} } {subscript} {superscript}
  109.     }
  110. }
  111.  
  112. # bind underscore and caret:
  113. ascii 0x5f <s> smartSubscripts "TeX"
  114. ascii 0x5e <s> smartSuperscripts "TeX"
  115.  
  116. #--------------------------------------------------------------------------
  117. # Escapes and exceptions:
  118. #--------------------------------------------------------------------------
  119.  
  120. proc literalChar {} {
  121.     return [expr {[lookAt [expr [getPos] - 1]] == "\\"}]
  122. }
  123.  
  124. proc escapeSmartStuff {} {
  125.     if {![isSelection]} then {
  126.         set pos [getPos]
  127.         # Escape double quotes:
  128.         if { $pos > 1 } then {
  129.             set pos2 [expr $pos - 2]
  130.             if { [getText $pos2 $pos] == "''" } then {
  131.                 replaceText $pos2 $pos {"}
  132.                 return
  133.             } elseif { [getText $pos2 $pos] == "``" } then {
  134.                 replaceText $pos2 $pos {"}
  135.                 return
  136.             }
  137.         }
  138.         # Escape single quote:
  139.         if { $pos > 0 } then {
  140.             set pos1 [expr $pos - 1]
  141.             if { [lookAt $pos1] == "`" } then {
  142.                 backSpace
  143.                 insertText {'}
  144.                 return
  145.             }
  146.         }
  147.         # Escape dots:
  148.         if { $pos > 5 } then {
  149.             set pos6 [expr $pos - 6]
  150.             if { [getText $pos6 $pos] == "\\ldots" } then {
  151.                 replaceText $pos6 $pos {...}
  152.                 return
  153.             }
  154.         }
  155.         # Escape underscore:
  156.         if { $pos > 1 && [maxPos] > [expr $pos + 1] } then {
  157.             set begPos [expr $pos - 2]
  158.             set endPos [expr $pos + 2]
  159.             if { [getText $begPos $endPos] == "_\{\}Ñ" } then {
  160.                 replaceText $begPos $endPos {_}
  161.                 return
  162.             }
  163.         }
  164.         # Escape caret:
  165.         if { $pos > 1 && [maxPos] > [expr $pos + 1] } then {
  166.             set begPos [expr $pos - 2]
  167.             set endPos [expr $pos + 2]
  168.             if { [getText $begPos $endPos] == "^\{\}Ñ" } then {
  169.                 replaceText $begPos $endPos {^}
  170.                 return
  171.             }
  172.         }
  173.     }
  174.     backSpace
  175. }
  176.  
  177. # bind delete key:
  178. ascii 0x08 escapeSmartStuff "TeX"
  179.  
  180. #--------------------------------------------------------------------------
  181. # Smart paragraph filling:
  182. #--------------------------------------------------------------------------
  183.  
  184. ## 
  185.  # Implements a    more sophisticated fillParagraph function, which deals
  186.  # with    pre-indented paragraphs. Thus it won't wreck visually formatted
  187.  # text    files (such    as itemised    lists and equations in LaTeX files).
  188.  ##
  189.  
  190. ## 
  191.  # Known bugs: 
  192.  #
  193.  # Filling a large paragraph which overlaps the top of the
  194.  # screen causes a re-draw error, in which the whole paragraph
  195.  # is draw in the on-screen window when some of it should not
  196.  # be visible. Thus it appears to over-write some of the text 
  197.  # below. Fortunately this is an illusion (scroll up and down
  198.  # a page and all is ok). This is a bug in Alpha's 'replaceText'
  199.  # routine.
  200.  #
  201.  ##
  202.  
  203. ## 
  204.  #    Currently the following    commands in    LaTeX signify a    new    paragraph:
  205.  # 
  206.  #       "begin|end|(protect\)label|(sub)*section|centerline|paragraph|chapter|item|bibitem|intertext"
  207.  # 
  208.  #    as well    as a blank line, '$$', and '\\'
  209.  ##
  210.  
  211. bind 'i' <c> texFillParagraph "TeX"
  212.  
  213. proc texFillParagraph {} {
  214.     if {[getPos] == [selEnd]} {
  215.         fillOneParagraph
  216.     } else {    
  217.         set start [getPos]
  218.         set end [selEnd]
  219.         set p $start
  220.         while { $p < $end } {
  221.             goto $p
  222.             set p [texFillParagraph]
  223.         }
  224.         goto $start
  225.     }
  226. }
  227.  
  228. proc fillOneParagraph {} {
  229.     global leftFillColumn fillColumn
  230.     
  231.     getWinInfo a
  232.     set tabs $a(tabsize)
  233.  
  234.     set pos [getPos]
  235.     # find nearest text to grab hold of 
  236.     # to try and maintain cursor position
  237.     if { [lookAt $pos] != " " } {
  238.         set grab [getText $pos [expr $pos +20]]
  239.         set grabdiff 0
  240.     } else {
  241.         backwardWord
  242.         set p2 [getPos]
  243.         set grab [getText $p2 [expr $pos +20]]
  244.         set grabdiff [expr $pos - $p2]
  245.     }
  246.     
  247.     set start [paraStart $pos] 
  248.     set end [paraFinish $pos]
  249.     # get the leading whitespace of the current line
  250.     set res [search -s -n -f 1 -r 1 "^\[ \t\]*" [lineStart $pos]]
  251.     
  252.     # convert it to minimal form: tabs then spaces, stored in 'front'
  253.     set sp [string range "              " 1 $tabs ]
  254.     regsub -all $sp [eval getText $res] "\t" front
  255.     regsub -all "\[ \]+\t" $front "\t" front
  256.     # get the length of the indent
  257.     regsub -all "\t" $front $sp lfront
  258.     set left [string length $lfront]
  259.  
  260.     # fill the text
  261.     regsub -all "\[ \t\r\]+" [string trim [getText $start $end]] " " text
  262.     # turn single spaces at end of sentences into double
  263. #     regsub -all {(([^A-Z@]|\\@)[.?!]) } $text {\1  } text
  264. #     regsub -all {(([^A-Z@]|\\@)[.?!]([])]|'|'')?) } $text {\1  } text
  265.     regsub -all {(([^A-Z@]|\\@)[.?!][])']?) } $text {\1  } text
  266.     
  267.     # temporarily adjust the fillColumns
  268.     set ol $leftFillColumn
  269.     set or $fillColumn
  270.     set leftFillColumn 0
  271.     set fillColumn [expr $fillColumn - $left]
  272.         
  273.     # break and indent the paragraph
  274.     regsub -all "\r" "\r[string trimright [breakIntoLines $text]]" "\r${front}" text
  275.     
  276.     # don't replace if nothing's changed
  277.     if { "$text\r" != "\r[getText $start $end]" } {
  278.         replaceText $start $end "[string range "$text" 1 end]\r"
  279.         set p [fillFind $text $grab]
  280.         if { $p == -1 } {
  281.             goto $pos
  282.         } else {
  283.             goto [expr $start + $p + $grabdiff -1]
  284.         }
  285.     }
  286.     
  287.     set leftFillColumn $ol
  288.     set fillColumn  $or
  289.     # in case we wish to fill a region
  290.     return $end
  291. }
  292.  
  293. proc fillFind { text search } {
  294.     if { ![string length $search] } {
  295.         return -1
  296.     }
  297.     
  298.     set pos [string first $search $text]
  299.     if { $pos != -1 } {
  300.         return $pos
  301.     } else {
  302.         set search [string range $search 0 [expr [string length $search] -5]]
  303.         return [fillFind $text $search]
  304.     }
  305. }
  306.  
  307. proc paraStart {pos} {
  308.     global mode
  309.     if {$pos == [maxPos]} {incr pos -1}
  310.     set pos [lineStart $pos]
  311.     if { $mode == "TeX" || $mode == "Bib" } {
  312.         set paraCommands {begin|end|(protect\\)?label|(sub)*section|paragraph|centerline|caption|chapter|item|bibitem|intertext}
  313.         set startPara {(\\\\[ \t]*$|^[ \t]*(\$\$[ \t]*|(%+.*|(\\(}
  314.         append startPara $paraCommands {)(\[.*\]|\{.*\}|Ñ)*[ \t]*)+))?$)}
  315.     } else {
  316.         set startPara {^([ \t]*|([\\%].*))$}
  317.     }
  318.     set res [search -s -n -f 0 -r 1 -l 0 "$startPara" $pos]
  319.     if {![string length $res] || $res == "0 0" } {return 0}
  320.     if { [lindex $res 0] == $pos } {
  321.         return $pos
  322.     } else {
  323.         return [nextLineStart [lindex $res 0]]
  324.     }
  325.     
  326. }
  327.  
  328. proc paraFinish {pos} {
  329.     global mode
  330.     set pos [lineStart $pos]
  331.     set end [maxPos]
  332.     if { $mode == "TeX" || $mode == "Bib" } {
  333.         set paraCommands {begin|end|(protect\\)?label|(sub)*section|paragraph|centerline|caption|chapter|item|bibitem|intertext}
  334.         set endPara {^[ \t]*(\$\$[ \t]*|(%+.*|(\\(}
  335.         append endPara $paraCommands {)(\[.*\]|\{.*\}|Ñ)*[ \t]*)+))?$}
  336.     } else {
  337.         set endPara {^([ \t]*|([\\%].*))$}
  338.     }
  339.     
  340.     set res [search -s -n -f 1 -r 1 -l $end "$endPara" $pos]
  341.     if {![string length $res]} {return $end}
  342.     if { [lindex $res 0] == $pos } {
  343.         return [nextLineStart $pos]
  344.     }
  345.     set res2 [search -s -n -f 1 -r 1 -l $end {\\\\[ \t]*$} $pos]
  346.     if [string length $res2] {
  347.         if { [lindex $res2 0] < [lindex $res 0] } {
  348.             return [nextLineStart [lindex $res2 0]]
  349.         }
  350.     }
  351.  
  352.     return [lindex $res 0]
  353.     
  354. }
  355.  
  356.